home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / dev / gg / ncurses-5.3.lha / ncurses-5.3 / tack / sysdep.c < prev    next >
C/C++ Source or Header  |  2002-10-24  |  10KB  |  502 lines

  1. /*
  2. ** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
  3. ** 
  4. ** This file is part of TACK.
  5. ** 
  6. ** TACK is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2, or (at your option)
  9. ** any later version.
  10. ** 
  11. ** TACK is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  15. ** 
  16. ** You should have received a copy of the GNU General Public License
  17. ** along with TACK; see the file COPYING.  If not, write to
  18. ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19. ** Boston, MA 02111-1307, USA.
  20. */
  21. /*
  22.  * Operating system dependent functions.  We assume the POSIX API.
  23.  * Note: on strict-POSIX systems (including BSD/OS) the select_delay_type
  24.  * global has no effect.
  25.  */
  26.  
  27. #include <signal.h>    /* include before curses.h to work around glibc bug */
  28.  
  29. #include <tack.h>
  30.  
  31. #include <term.h>
  32. #include <errno.h>
  33.  
  34. #if defined(__BEOS__)
  35. #undef false
  36. #undef true
  37. #include <OS.h>
  38. #endif
  39.  
  40. #if HAVE_SELECT
  41. #if HAVE_SYS_TIME_H && HAVE_SYS_TIME_SELECT
  42. #include <sys/time.h>
  43. #endif
  44. #if HAVE_SYS_SELECT_H
  45. #include <sys/select.h>
  46. #endif
  47. #endif
  48.  
  49. MODULE_ID("$Id: sysdep.c,v 1.11 2002/04/21 19:40:43 tom Exp $")
  50.  
  51. #if DECL_ERRNO
  52. extern int errno;
  53. #endif
  54.  
  55. #ifdef TERMIOS
  56. #define PUT_TTY(fd, buf) tcsetattr(fd, TCSAFLUSH, buf)
  57. #else
  58. #define PUT_TTY(fd, buf) stty(fd, buf)
  59. #endif
  60.  
  61. /* globals */
  62. int tty_frame_size;        /* asynch frame size times 2 */
  63. unsigned long tty_baud_rate;    /* baud rate - bits per second */
  64. int not_a_tty;            /* TRUE if output is not a tty (i.e. pipe) */
  65. int nodelay_read;        /* TRUE if NDELAY is set */
  66.  
  67. #ifdef TERMIOS
  68. #define TTY_IS_NOECHO    !(new_modes.c_lflag & ECHO)
  69. #define TTY_IS_OUT_TRANS (new_modes.c_oflag & OPOST)
  70. #define TTY_IS_CHAR_MODE !(new_modes.c_lflag & ICANON)
  71. #define TTY_WAS_CS8 ((old_modes.c_cflag & CSIZE) == CS8)
  72. #define TTY_WAS_XON_XOFF (old_modes.c_iflag & (IXON|IXOFF))
  73. #else
  74. #define TTY_IS_NOECHO    !(new_modes.sg_flags & (ECHO))
  75. #define TTY_IS_OUT_TRANS (new_modes.sg_flags & (CRMOD))
  76. #define TTY_IS_CHAR_MODE (new_modes.sg_flags & (RAW|CBREAK))
  77. #define TTY_WAS_CS8     (old_modes.sg_flags & (PASS8))
  78. #define TTY_WAS_XON_XOFF (old_modes.sg_flags & (TANDEM|MDMBUF|DECCTQ))
  79. #endif
  80.  
  81. static TTY old_modes, new_modes;
  82.  
  83. void catchsig(void);
  84.  
  85. /*
  86.  * These are a sneaky way of conditionalizing bit unsets so strict-POSIX
  87.  * systems won't see them.
  88.  */
  89. #ifndef XCASE
  90. #define XCASE    0
  91. #endif
  92. #ifndef OLCUC
  93. #define OLCUC    0
  94. #endif
  95. #ifndef IUCLC
  96. #define IUCLC    0
  97. #endif
  98. #ifndef TABDLY
  99. #define    TABDLY    0
  100. #endif
  101. #ifndef IXANY
  102. #define    IXANY    0
  103. #endif
  104.  
  105. void
  106. tty_raw(int minch GCC_UNUSED, int mask)
  107. {                /* set tty to raw noecho */
  108.     new_modes = old_modes;
  109. #ifdef TERMIOS
  110. #if HAVE_SELECT
  111.     new_modes.c_cc[VMIN] = 1;
  112. #else
  113.     new_modes.c_cc[VMIN] = minch;
  114. #endif
  115.     new_modes.c_cc[VTIME] = 2;
  116.     new_modes.c_lflag &=
  117.         ~(ISIG | ICANON | XCASE | ECHO | ECHOE | ECHOK | ECHONL);
  118. #ifdef LOBLK
  119.     new_modes.c_lflag &= ~LOBLK;
  120. #endif
  121.     new_modes.c_oflag &= ~(OPOST | OLCUC | TABDLY);
  122.     if (mask == ALLOW_PARITY) {
  123.         new_modes.c_cflag &= ~(CSIZE | PARENB | HUPCL);
  124.         new_modes.c_cflag |= CS8;
  125.     }
  126.     new_modes.c_iflag &=
  127.         ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL |
  128.         IUCLC | IXON | IXANY | IXOFF);
  129. #else
  130.     new_modes.sg_flags |= RAW;
  131. #endif
  132.     if (not_a_tty)
  133.         return;
  134.     PUT_TTY(fileno(stdin), &new_modes);
  135. }
  136.  
  137. void 
  138. tty_set(void)
  139. {                /* set tty to special modes */
  140.     new_modes = old_modes;
  141. #ifdef TERMIOS
  142.     new_modes.c_cc[VMIN] = 1;
  143.     new_modes.c_cc[VTIME] = 1;
  144.     new_modes.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
  145. #if defined(ONLCR) && defined(OCRNL) && defined(ONLRET) && defined(OFILL)
  146.     new_modes.c_oflag &= ~(ONLCR | OCRNL | ONLRET | OFILL);
  147. #else
  148.     new_modes.c_oflag &= ~(OPOST);
  149. #endif
  150.     if (char_mask == ALLOW_PARITY)
  151.         new_modes.c_iflag &= ~ISTRIP;
  152.     switch (select_xon_xoff) {
  153.     case 0:
  154.         new_modes.c_iflag &= ~(IXON | IXOFF);
  155.         break;
  156.     case 1:
  157. #if defined(sequent) && sequent
  158.         /* the sequent System V emulation is broken */
  159.         new_modes = old_modes;
  160.         new_modes.c_cc[VEOL] = 6;    /* control F  (ACK) */
  161. #endif
  162.         new_modes.c_iflag |= IXON | IXOFF;
  163.         break;
  164.     }
  165.     switch (select_delay_type) {
  166.     case 0:
  167. #ifdef NLDLY
  168.         new_modes.c_oflag &=
  169.             ~(NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
  170. #endif    /* NLDLY */
  171.         break;
  172.     case 1:
  173. #ifdef NLDLY
  174.         new_modes.c_oflag &=
  175.             ~(NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
  176. #endif    /* NLDLY */
  177. #ifdef NL1
  178.         new_modes.c_oflag |= NL1 | CR2;
  179. #endif    /* NL1 */
  180.         break;
  181.     }
  182.     if (!(new_modes.c_oflag & ~OPOST))
  183.         new_modes.c_oflag &= ~OPOST;
  184. #else
  185.     new_modes.sg_flags |= RAW;
  186.     if (not_a_tty)
  187.         return;
  188. #endif
  189.     PUT_TTY(fileno(stdin), &new_modes);
  190. }
  191.  
  192.  
  193. void 
  194. tty_reset(void)
  195. {                /* reset the tty to the original modes */
  196.     fflush(stdout);
  197.     if (not_a_tty)
  198.         return;
  199.     PUT_TTY(fileno(stdin), &old_modes);
  200. }
  201.  
  202.  
  203. void 
  204. tty_init(void)
  205. {                /* ATT terminal init */
  206. #if defined(F_GETFL) && defined(O_NDELAY)
  207.     int flags;
  208.  
  209.     flags = fcntl(fileno(stdin), F_GETFL, 0);
  210.     nodelay_read = flags & O_NDELAY;
  211. #else
  212.     nodelay_read = FALSE;
  213. #endif
  214.     not_a_tty = FALSE;
  215.     if (GET_TTY(fileno(stdin), &old_modes) == -1) {
  216.         if (errno == ENOTTY) {
  217.             tty_frame_size = 20;
  218.             not_a_tty = TRUE;
  219.             return;
  220.         }
  221.         printf("tcgetattr error: %d\n", errno);
  222.         exit(1);
  223.     }
  224.     /* if TAB3 is set then setterm() wipes out tabs (ht) */
  225.     new_modes = old_modes;
  226. #ifdef TERMIOS
  227. #ifdef TABDLY
  228.     new_modes.c_oflag &= ~TABDLY;
  229. #endif    /* TABDLY */
  230. #endif
  231.     if (PUT_TTY(fileno(stdin), &new_modes) == -1) {
  232.         printf("tcsetattr error: %d\n", errno);
  233.         exit(1);
  234.     }
  235. #ifdef sequent
  236.     /* the sequent ATT emulation is broken soooo. */
  237.     old_modes.c_cflag &= ~(CSIZE | CSTOPB);
  238.     old_modes.c_cflag |= CS7 | PARENB;
  239. #endif
  240.     catchsig();
  241. #ifdef TERMIOS
  242.     switch (old_modes.c_cflag & CSIZE) {
  243. #if defined(CS5) && (CS5 != 0)
  244.     case CS5:
  245.         tty_frame_size = 10;
  246.         break;
  247. #endif
  248. #if defined(CS6) && (CS6 != 0)
  249.     case CS6:
  250.         tty_frame_size = 12;
  251.         break;
  252. #endif
  253. #if defined(CS7) && (CS7 != 0)
  254.     case CS7:
  255.         tty_frame_size = 14;
  256.         break;
  257. #endif
  258. #if defined(CS8) && (CS8 != 0)
  259.     case CS8:
  260.         tty_frame_size = 16;
  261.         break;
  262. #endif
  263.     }
  264.     tty_frame_size += 2 +
  265.         ((old_modes.c_cflag & PARENB) ? 2 : 0) +
  266.         ((old_modes.c_cflag & CSTOPB) ? 4 : 2);
  267. #else
  268.     tty_frame_size = 6 +
  269.         (old_modes.sg_flags & PASS8) ? 16 : 14;
  270. #endif
  271. }
  272.  
  273. /*
  274. **    stty_query(question)
  275. **
  276. **    Does the current driver settings have this property?
  277. */
  278. int
  279. stty_query(int q)
  280. {
  281.     switch (q) {
  282.         case TTY_NOECHO:
  283.         return TTY_IS_NOECHO;
  284.     case TTY_OUT_TRANS:
  285.         return TTY_IS_OUT_TRANS;
  286.     case TTY_CHAR_MODE:
  287.         return TTY_IS_CHAR_MODE;
  288.     }
  289.     return (-1);
  290. }
  291.  
  292. /*
  293. **    initial_stty_query(question)
  294. **
  295. **    Did the initial driver settings have this property?
  296. */
  297. int
  298. initial_stty_query(int q)
  299. {
  300.     switch (q) {
  301.     case TTY_8_BIT:
  302.         return TTY_WAS_CS8;
  303.     case TTY_XON_XOFF:
  304.         return TTY_WAS_XON_XOFF;
  305.     }
  306.     return (-1);
  307. }
  308.  
  309. #if HAVE_SELECT && defined(FD_ZERO)
  310. static int
  311. char_ready(void)
  312. {
  313.     int n;
  314.     fd_set ifds;
  315.     struct timeval tv;
  316.  
  317.     FD_ZERO(&ifds);
  318.     FD_SET(fileno(stdin), &ifds);
  319.     tv.tv_sec = 0;
  320.     tv.tv_usec = 200000;
  321.     n = select(fileno(stdin)+1, &ifds, NULL, NULL, &tv);
  322.     return (n != 0);
  323. }
  324.  
  325. #else
  326. #ifdef FIONREAD
  327. int
  328. char_ready(void)
  329. {
  330.     int i, j;
  331.  
  332.     /* the following loop has to be tuned for each computer */
  333.     for (j = 0; j < 1000; j++) {
  334.         ioctl(fileno(stdin), FIONREAD, &i);
  335.         if (i)
  336.             return i;
  337.     }
  338.     return i;
  339. }
  340.  
  341. #else
  342. #if defined(__BEOS__)
  343. int
  344. char_ready(void)
  345. {
  346.     int n = 0;
  347.     int howmany = ioctl(0, 'ichr', &n);
  348.     return (howmany >= 0 && n > 0);
  349. }
  350. #else
  351. #define char_ready() 1
  352. #endif
  353. #endif
  354. #endif
  355.  
  356. /*
  357. **    spin_flush()
  358. **
  359. **    Wait for the input stream to stop.
  360. **    Throw away all input characters.
  361. */
  362. void
  363. spin_flush(void)
  364. {
  365.     unsigned char buf[64];
  366.  
  367.     fflush(stdout);
  368.     event_start(TIME_FLUSH);    /* start the timer */
  369.     do {
  370.         if (char_ready()) {
  371.             (void) read(fileno(stdin), &buf, sizeof(buf));
  372.         }
  373.     } while (event_time(TIME_FLUSH) < 400000);
  374. }
  375.  
  376. /*
  377. **    read_key(input-buffer, length-of-buffer)
  378. **
  379. **    read one function key from the input stream.
  380. **    A null character is converted to 0x80.
  381. */
  382. void 
  383. read_key(char *buf, int max)
  384. {
  385.     int got, ask, i, l;
  386.     char *s;
  387.  
  388.     *buf = '\0';
  389.     s = buf;
  390.     fflush(stdout);
  391.     /* ATT unix may return 0 or 1, Berkeley Unix should be 1 */
  392.     while (read(fileno(stdin), s, 1) == 0);
  393.     ++s;
  394.     --max;
  395.     while (max > 0 && (ask = char_ready())) {
  396.         if (ask > max) {
  397.             ask = max;
  398.         }
  399.         if ((got = read(fileno(stdin), s, ask))) {
  400.             s += got;
  401.         } else {
  402.             break;
  403.         }
  404.         max -= got;
  405.     }
  406.     *s = '\0';
  407.     l = s - buf;
  408.     for (s = buf, i = 0; i < l; i++) {
  409.         if ((*s & 0x7f) == 0) {
  410.             /* convert nulls to 0x80 */
  411.             *(unsigned char *)s = 128;
  412.         } else {
  413.             /* strip high order bits (if any) */
  414.             *s &= char_mask;
  415.         }
  416.     }
  417. }
  418.  
  419.  
  420. void 
  421. ignoresig(void)
  422. {
  423.     /* ignore signals */
  424.     signal(SIGINT, SIG_IGN);
  425.     signal(SIGHUP, SIG_IGN);
  426.     signal(SIGQUIT, SIG_IGN);
  427.     signal(SIGTERM, SIG_IGN);
  428.     signal(SIGALRM, SIG_IGN);
  429. }
  430.  
  431.  /*
  432.     onintr( )
  433.  
  434.  is the interrupt handling routine onintr turns off interrupts while doing
  435.     clean-up
  436.  
  437.  onintr always exits fatally
  438.  */
  439.  
  440.  
  441. static RETSIGTYPE 
  442. onintr(int sig GCC_UNUSED)
  443. {
  444.     ignoresig();
  445.     tty_reset();
  446.     exit(1);
  447. }
  448.  
  449.  
  450.  /*
  451.     catchsig( )
  452.  
  453.  set up to field interrupts (via function onintr( )) so that if interrupted
  454.     we can restore the correct terminal modes
  455.  
  456.  catchsig simply returns
  457.  */
  458.  
  459.  
  460. void 
  461. catchsig(void)
  462. {
  463.     if ((signal(SIGINT, SIG_IGN)) == SIG_DFL)
  464.         signal(SIGINT, onintr);
  465.  
  466.     if ((signal(SIGHUP, SIG_IGN)) == SIG_DFL)
  467.         signal(SIGHUP, onintr);
  468.  
  469.     if ((signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
  470.         signal(SIGQUIT, onintr);
  471.  
  472.     if ((signal(SIGTERM, SIG_IGN)) == SIG_DFL)
  473.         signal(SIGTERM, onintr);
  474.  
  475. }
  476.  
  477. /*
  478. **    alarm_event(sig)
  479. **
  480. **    Come here for an alarm event
  481. */
  482. static void
  483. alarm_event(
  484.     int sig GCC_UNUSED)
  485. {
  486.     no_alarm_event = 0;
  487. }
  488.  
  489. /*
  490. **    set_alarm_clock(seconds)
  491. **
  492. **    Set the alarm clock to fire in <seconds>
  493. */
  494. void
  495. set_alarm_clock(
  496.     int seconds)
  497. {
  498.     signal(SIGALRM, alarm_event);
  499.     no_alarm_event = 1;
  500.     (void) alarm(seconds);
  501. }
  502.